梦入琼楼寒有月,行过石树冻无烟

Python 数据结构

python cookbook 是 python3&2 等版本中适合开发者进阶的一本书,其中主要讲解了核心语法,同时也是 Python3 的参考书,所有代码都是在 Python 3.3 的版本下进行编写和测试的。

此书主要对数据结构等进行非常详细的介绍和案例处理,基本上包含了目前所有 Python 可以涉猎的内容。

1
编写的主要目的就是在 Python cookbook 所忽视的基础问题上,增加一点描述和更加通俗的理解方便进行阅读。

解构器

解构序列赋值多个变量

1
现在有一个包含 N 个元素的元组或者是序列,怎样将它里面的值解构后同时赋值给 N 个变量?

首先我们需要知道,元组(tuple) 了类似于列表,元组的区别在于一旦赋值给元组,就无法更改元组的元素,而列表可以更改

1
元组是将所有元素放在括号中的,也就是 my_tuple = (1,2),括号是可选的,它可以包含 int、float、list、strig 等

而题目要求是将包含 n 个的元组变量或数据,来将它里面的值解构后复制给其他变量:

1
2
3
4
5
6
7
p = (4, 5)

# 将元组解构赋值给多个变量
x, y = p

print(x) # 4
print(y) # 5

在 python 中,任何序列或是可以 迭代 的对象,都可以通过赋值语句解构并赋值给多个变量,前提是变量和数量的序列是一样的,而且这适用于列表:

1
2
3
4
list = ['BNB', 'WBNB', 'BUSD']

get_bnb, get_wbnb, get_busd = list
print(get_bnb) #BNB

同时在书中也提供了一个列表(list) 包含 元组(tuple) 的示例,但数据类型是列表的序列:

1
2
3
4
5
6
7
data = [ 'ACME', 50, 91.1, (2012, 12, 21) ]

name, shares, price, date = data
print(date) # (2012, 12, 21)

name, shares, price, (year, mon, day) = data
print(year , mon , day) # 2012 12 21

实际上上述这种解构器复制可以用于任何可以 迭代的对象,包括字符串和文件等,同时对字符串则可以是:

1
2
3
4
str = 'Hello'
a, b, c, d, e = str

print(a,b,c,d,e, sep='') # H e l l o > Hello

上面我们使用了一个 python() 函数中的 sep 参数(只有 python() 函数可以使用),以此来去掉多余部分的空格,如何在Python中使用sep打印 (adamsmith.haus),在此连接中有较为详细的介绍。

假设有时候我们只需要解构一部分,而忽略掉其他的值,那么我们就可以通过使用 _ 的方式来进行忽略:

1
2
3
4
5
data = [ 'ACME', 50, 91.1, (2012, 12, 21) ]

_, shares, price, _ = data

print(shares) # 50
1
如果我们的元素个数,超出了变量的个数,那么将会抛出一个 ```ValueError: need more than 2 values to unpack``` 错误,为了避免此类问题,我们可以使用 ```*``` 解决

在书中,这一章节主要被称之为:“将可迭代的对象赋值给多个变量”,根据提议和问题来进行理解,就是说对象的数量太多,而变量的数量太少不对应所造成的问题,可以通过 * 进行解决,也就是说后面的对象,都解构给了 date 这个变量。

1
2
3
4
data = [ 'ACME', 91.1, (2012, 12, 21), (2022, 3, 18)  ]

name, pcrice, date = data
print(date) #[(2012, 12, 21), (2022, 3, 18)]

为了更好的展示数据类型的改变,我们直接使用书上所进行展示的元组(tuple) 来进行演示:

1
2
3
4
record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212')

name, email, *phone = record
print(type(phone))

最后原来 recird 的元组通过使用 * 的方式,输出为了一个列表,上面 phone 解构出的也永远都是列表类型,因此在特殊时候我们还需要进行转换

解构在迭代器的使用

迭代解构是专门为解构不确定的个数或任意可迭代的对象而设计的,通过 * 可以很容易利用解构器的方式结构出元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
records = [  
('foo', 1, 2),
('bar', 'hey'),
('foo', 3, 4),
]


def do_foo(x, y):
print('do_foo', x, y)


def do_bar(s):
print('do_bar', s)


for tag, *args in records:
if tag == 'foo':
do_foo(*args)

elif tag == 'bar':
do_bar(*args)

如果根据上述 Code 运行以及输出后都不理解的话,我们可以看分解后的数据

我们可以将迭代器中的 for tag, *args in records 理解为 tag, *args = records,之后这样 tag 就对应了 foo,bar,foo*args 对应的就是之后的对象。

因为有时候 list 元素中,可能会有 1~2 个索引值,为了通用性所以写了 *,之后就是添加循环迭代以及在 if 语句中引入对应的函数即可循环迭代 list 中的数据。

⬅️ Go back